package umg.os.kernel;

import java.util.ArrayList;
import java.util.List;

import umg.os.kernel.scheduler.Scheduler;
import umg.os.process.ProcessControlBlock;

public final class Dispatcher {

	private static final Dispatcher singletonInstance = new Dispatcher();
	private List<DispatcherSwitchProcessListener> dispatcherSwitchProcessListeners;
	
	
	private Dispatcher() {
		dispatcherSwitchProcessListeners = new ArrayList<DispatcherSwitchProcessListener>();
		dispatcherSwitchProcessListeners.add(Scheduler.getInstance());
	}
	
	public static Dispatcher getInstance() {
		return singletonInstance;
	}
	
	public void switchExecutingProcess() {
		ProcessControlBlock processThatUsedToBeExecuting = Kernel.getInstance().stopExecutingProcess();
		if (processThatUsedToBeExecuting != null) {
			for (DispatcherSwitchProcessListener dspl : dispatcherSwitchProcessListeners) {
				dspl.dispatcherJustSwitch(processThatUsedToBeExecuting);
			}
		} else { 
			System.err.println(this.getClass().getName()+": There was no process running...");
		}
		ProcessControlBlock nextProcessToExecute = Scheduler.getInstance().requestNextProcessToExecute();
		if (nextProcessToExecute == null) {
			System.err.println("No process is waiting or its arrival times have not been reached yet...");
			//throw new NullPointerException("The newProcessToExecute cannot be null");
		}
		Kernel.getInstance().startExecutingProcess(nextProcessToExecute);
	}
	
	public interface DispatcherSwitchProcessListener {
		
		void dispatcherJustSwitch(ProcessControlBlock processDeallocated);
		
	}

}
